home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / sig / sigMigrate.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  11KB  |  382 lines

  1. /* 
  2.  * sigMigrate.c --
  3.  *
  4.  *    Routines to handle signals for migrated procedures.
  5.  *
  6.  * Copyright (C) 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/sig/sigMigrate.c,v 9.10 92/01/06 15:17:15 kupfer Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14.  
  15. #include <sprite.h>
  16. #include <stdlib.h>
  17. #include <sig.h>
  18. #include <sync.h>
  19. #include <list.h>
  20. #include <proc.h>
  21. #include <procMigrate.h>
  22. #include <status.h>
  23. #include <sched.h>
  24. #include <sigInt.h>
  25. #include <rpc.h>
  26. #include <bstring.h>
  27. #include <stdio.h>
  28.  
  29. /* 
  30.  * Information sent when sending a signal.  Needed when doing a callback.
  31.  */
  32.  
  33. typedef struct {
  34.     Proc_PID             processID;
  35.     int                sigNum;
  36.     int                code;
  37. } DeferInfo;
  38.  
  39. static void DeferSignal _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  40.  
  41.  
  42. /*
  43.  *----------------------------------------------------------------------
  44.  *
  45.  * SigMigSend --
  46.  *
  47.  *    Send a signal to a migrated process.  The current host is found
  48.  *    in the process control block for the process.  
  49.  *
  50.  * Results:
  51.  *    SUCCESS or an error condition from the RPC or remote node.
  52.  *
  53.  * Side effects:
  54.  *    A remote procedure call is performed and the process is signalled
  55.  *    on its currently executing host.
  56.  *
  57.  *----------------------------------------------------------------------
  58.  */
  59.  
  60. ReturnStatus
  61. SigMigSend(procPtr, sigNum, code, addr)
  62.     register Proc_ControlBlock     *procPtr; /* The migrated process */
  63.     int                  sigNum;
  64.     int                  code;
  65.     Address              addr;
  66. {
  67.     ReturnStatus status;
  68.     Proc_PID processID;
  69.     Proc_PID remoteProcessID;
  70.     int remoteHostID;
  71.     Proc_ControlBlock     *callerProcPtr; /* The calling process */
  72.     Boolean locked;
  73.  
  74.     if (proc_MigDebugLevel > 4) {
  75.     printf("SigMigSend(%x, %d, %d) entered.\n", procPtr->processID,
  76.            sigNum, code);
  77.     }
  78.  
  79. again:
  80.     processID = procPtr->processID;
  81.     if (procPtr->genFlags & (PROC_MIG_PENDING | PROC_MIGRATING)) {
  82.     /*
  83.      * If the current process is a user process, wait for the
  84.      * process to finish migrating before signalling it. If
  85.      * it's a kernel process, start a background process to
  86.      * wait for migration and deliver the signal asynchronously.
  87.      * When calling Proc_WaitForMigration, make sure the process isn't
  88.      * locked.
  89.      */
  90.     callerProcPtr = Proc_GetActualProc();
  91.     if (callerProcPtr->genFlags & PROC_KERNEL) {
  92.         DeferInfo *infoPtr;
  93.  
  94.         infoPtr = (DeferInfo *) malloc(sizeof(*infoPtr));
  95.         infoPtr->processID = procPtr->processID;
  96.         infoPtr->sigNum = sigNum;
  97.         infoPtr->code = code;
  98.         Proc_CallFunc(DeferSignal, (ClientData) infoPtr, 0);
  99.         return(SUCCESS);
  100.     }
  101.         Proc_Unlock(procPtr);
  102.     status = Proc_WaitForMigration(processID);
  103.     Proc_Lock(procPtr);
  104.     if ((procPtr->state != PROC_MIGRATED) ||
  105.         (procPtr->processID != processID)) {
  106.         /*
  107.          * Process is not now migrated.  Return PROC_INVALID_PID,
  108.          * which will make Sig_SendProc do a local send.
  109.          */
  110.         return(PROC_INVALID_PID);
  111.     }
  112.     if (status != SUCCESS) {
  113.         return(status);
  114.     }
  115.     }
  116.     remoteProcessID = procPtr->peerProcessID;
  117.     remoteHostID = procPtr->peerHostID;
  118.     if (remoteHostID == (int) NIL) {
  119.     printf("Warning: SigMigSend: process %x has no peer.\n", processID);
  120.     return(PROC_INVALID_PID);
  121.     }
  122.     
  123.  
  124.     /*
  125.      * It is necessary to unlock the process while sending the remote
  126.      * signal, since the signal could cause the remote node to come back
  127.      * and lock the process again.
  128.      */
  129.     Proc_Unlock(procPtr);
  130.     locked = FALSE;
  131.     status = SigSendRemoteSignal(remoteHostID, sigNum, code,
  132.                   remoteProcessID, FALSE, addr);
  133.  
  134.     if (proc_MigDebugLevel > 4) {
  135.     printf("SigMigSend returning %x.\n", status);
  136.     }
  137.  
  138.     if (status != SUCCESS) {
  139.     if (status == PROC_INVALID_PID) {
  140.         Proc_ControlBlock *newProcPtr;
  141.         newProcPtr = Proc_LockPID(processID);
  142.         if (newProcPtr == (Proc_ControlBlock *) NIL) {
  143.         /*
  144.          * This is what we're hoping for: the process doesn't
  145.          * exist on either the remote host or the local host.
  146.          */
  147.         goto done;
  148.         }
  149.         locked = TRUE;
  150.         if (procPtr != newProcPtr) {
  151.         panic("SigMigSend: locked wrong process (continuable).\n");
  152.         goto done;
  153.         }
  154.         /*
  155.          * Same process.
  156.          */
  157.         if (procPtr->state == PROC_MIGRATED &&
  158.         procPtr->peerHostID != remoteHostID) {
  159.         if (proc_MigDebugLevel > 1) {
  160.             printf("SigMigSend: process %x changed hosts during signal; retrying.\n",
  161.                    processID);
  162.         }
  163.         
  164.         goto again;
  165.         }
  166.         if (procPtr->state != PROC_MIGRATED) {
  167.         if (proc_MigDebugLevel > 1) {
  168.             printf("SigMigSend: process %x no longer migrated.\n",
  169.                    processID);
  170.         }
  171.         goto done;
  172.         }
  173.     }        
  174.         
  175.         
  176.     if (proc_MigDebugLevel > 0) {
  177.         printf("Warning: SigMigSend:Error trying to signal %d to process %x (%x on host %d):\n\t%s\n",
  178.            sigNum, processID, remoteProcessID, remoteHostID,
  179.            Stat_GetMsg(status));
  180.     }
  181.     if (sigNum == SIG_KILL || status == PROC_INVALID_PID) {
  182.         if (proc_MigDebugLevel > 0) {
  183.         printf("SigMigSend: killing local copy of process %x.\n",
  184.                processID);
  185.         }
  186.         Proc_CallFunc(Proc_DestroyMigratedProc,
  187.               (ClientData) processID, 0);
  188.     }
  189.     }
  190.  
  191.     /*
  192.      * Give back the procPtr in the same state we found it (locked).
  193.      * Note that it may no longer refer to the same process (if the process
  194.      * has been recycled while we had it unlocked) but the caller should
  195.      * just unlock it and return.
  196.      */
  197.     done:
  198.     if (!locked) {
  199.     Proc_Lock(procPtr);
  200.     }
  201.     
  202.     return(status);
  203. }
  204.  
  205.  
  206. /*
  207.  *----------------------------------------------------------------------
  208.  *
  209.  * DeferSignal --
  210.  *
  211.  *    Wait for a process to migrate, then send it a signal. This
  212.  *    is done using the callback queue so the sender of the signal,
  213.  *    if a kernel process, doesn't block.
  214.  *
  215.  * Results:
  216.  *    None.
  217.  *
  218.  * Side effects:
  219.  *    The process doing the callback goes to sleep until the process
  220.  *    being signalled has migrated or been killed.
  221.  *
  222.  *----------------------------------------------------------------------
  223.  */
  224.  
  225. static void 
  226. DeferSignal(data, callInfoPtr)
  227.     ClientData data;
  228.     Proc_CallInfo *callInfoPtr;         /* Not used. */
  229. {
  230.     DeferInfo *infoPtr = (DeferInfo *) data;
  231.     ReturnStatus status;
  232.     Proc_ControlBlock *procPtr;
  233.  
  234.     status = Proc_WaitForMigration(infoPtr->processID);
  235.     if (status != SUCCESS) {
  236.     goto failure;
  237.     }
  238.     procPtr = Proc_LockPID(infoPtr->processID);
  239.     if (procPtr == (Proc_ControlBlock *) NIL) {
  240.     goto failure;
  241.     }
  242.     (void) SigMigSend(procPtr, infoPtr->sigNum, infoPtr->code, (Address) 0);
  243.     Proc_Unlock(procPtr);
  244.     return;
  245.  
  246.     failure:
  247.     if (proc_MigDebugLevel > 2) {
  248.     printf("DeferSignal: unable to send delayed signal to migrated process %x\n",
  249.            infoPtr->processID);
  250.     }
  251. }
  252.     
  253.  
  254. typedef struct {
  255.     int        sigHoldMask;
  256.     int        sigPendingMask;
  257.     int        sigActions[SIG_NUM_SIGNALS];
  258.     int        sigMasks[SIG_NUM_SIGNALS];
  259.     int        sigCodes[SIG_NUM_SIGNALS];
  260.     int        sigFlags;
  261. } EncapState;
  262.  
  263. #define COPY_STATE(from, to, field) to->field = from->field
  264.  
  265. /*
  266.  *----------------------------------------------------------------------
  267.  *
  268.  * Sig_GetEncapSize --
  269.  *
  270.  *    Determine the size of the encapsulated signal state.
  271.  *
  272.  * Results:
  273.  *    SUCCESS is returned directly; the size of the encapsulated state
  274.  *    is returned in infoPtr->size.
  275.  *
  276.  * Side effects:
  277.  *    None.
  278.  *
  279.  *----------------------------------------------------------------------
  280.  */
  281.  
  282. /* ARGSUSED */
  283. ReturnStatus
  284. Sig_GetEncapSize(procPtr, hostID, infoPtr)
  285.     Proc_ControlBlock *procPtr;            /* process being migrated */
  286.     int hostID;                    /* host to which it migrates */
  287.     Proc_EncapInfo *infoPtr;            /* area w/ information about
  288.                          * encapsulated state */
  289. {
  290.     infoPtr->size = sizeof(EncapState);
  291.     return(SUCCESS);    
  292. }
  293.  
  294.  
  295. /*
  296.  *----------------------------------------------------------------------
  297.  *
  298.  * Sig_EncapState --
  299.  *
  300.  *    Encapsulate the signal state of a process from the Proc_ControlBlock
  301.  *    and return it in the buffer provided.
  302.  *
  303.  * Results:
  304.  *    SUCCESS.  The buffer is filled.
  305.  *
  306.  * Side effects:
  307.  *    None.
  308.  *----------------------------------------------------------------------
  309.  */
  310.  
  311. /* ARGSUSED */
  312. ReturnStatus
  313. Sig_EncapState(procPtr, hostID, infoPtr, bufPtr)
  314.     register Proc_ControlBlock     *procPtr;  /* The process being migrated */
  315.     int hostID;                   /* host to which it migrates */
  316.     Proc_EncapInfo *infoPtr;           /* area w/ information about
  317.                         * encapsulated state */
  318.     Address bufPtr;               /* Pointer to allocated buffer */
  319. {
  320.     EncapState *encapPtr = (EncapState *) bufPtr;
  321.  
  322.     COPY_STATE(procPtr, encapPtr, sigHoldMask);
  323.     COPY_STATE(procPtr, encapPtr, sigPendingMask);
  324.     COPY_STATE(procPtr, encapPtr, sigFlags);
  325.     bcopy((Address) procPtr->sigActions, (Address) encapPtr->sigActions,
  326.       SIG_NUM_SIGNALS * sizeof(int));
  327.     bcopy((Address) procPtr->sigMasks, (Address) encapPtr->sigMasks,
  328.       SIG_NUM_SIGNALS * sizeof(int));
  329.     bcopy((Address) procPtr->sigCodes, (Address) encapPtr->sigCodes,
  330.       SIG_NUM_SIGNALS * sizeof(int));
  331.     return(SUCCESS);
  332. }
  333.  
  334.  
  335. /*
  336.  *----------------------------------------------------------------------
  337.  *
  338.  * Sig_DeencapState --
  339.  *
  340.  *    Get signal information from a Proc_ControlBlock from another host.
  341.  *    The information is contained in the parameter ``buffer''.
  342.  *
  343.  * Results:
  344.  *    SUCCESS.
  345.  *
  346.  * Side effects:
  347.  *    None.
  348.  *----------------------------------------------------------------------
  349.  */
  350.  
  351. /* ARGSUSED */
  352. ReturnStatus
  353. Sig_DeencapState(procPtr, infoPtr, bufPtr)
  354.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  355.     Proc_EncapInfo *infoPtr;          /* information about the buffer */
  356.     Address bufPtr;              /* buffer containing data */
  357. {
  358.     EncapState *encapPtr = (EncapState *) bufPtr;
  359.  
  360.     if (infoPtr->size != sizeof(EncapState)) {
  361.     if (proc_MigDebugLevel > 0) {
  362.         printf("Sig_DeencapState: warning: host %d tried to migrate onto this host with wrong structure size.  Ours is %d, theirs is %d.\n",
  363.            procPtr->peerHostID, sizeof(EncapState),
  364.            infoPtr->size);
  365.     }
  366.     return(PROC_MIGRATION_REFUSED);
  367.     }
  368.     COPY_STATE(encapPtr, procPtr, sigHoldMask);
  369.     COPY_STATE(encapPtr, procPtr, sigPendingMask);
  370.     procPtr->sigPendingMask &=
  371.     ~(Sig_NumberToMask(SIG_MIGRATE_TRAP) |
  372.       Sig_NumberToMask(SIG_MIGRATE_HOME));
  373.     COPY_STATE(encapPtr, procPtr, sigFlags);
  374.     bcopy((Address) encapPtr->sigActions, (Address) procPtr->sigActions,
  375.       SIG_NUM_SIGNALS * sizeof(int));
  376.     bcopy((Address) encapPtr->sigMasks, (Address) procPtr->sigMasks,
  377.       SIG_NUM_SIGNALS * sizeof(int));
  378.     bcopy((Address) encapPtr->sigCodes, (Address) procPtr->sigCodes,
  379.       SIG_NUM_SIGNALS * sizeof(int));
  380.     return(SUCCESS);
  381. }
  382.